from sqlalchemy import Table, Unicode, UnicodeText, Column, Integer, ForeignKey, and_, select, desc
from sqlalchemy.orm import mapper, relation, backref

from brainfreeze import OneToOneMapperExtension

from tortuga.database import metadata
from tortuga.models.util import Base
from tortuga.models.revision import Revision, revision_table

__all__ = ['Gadget', 'BasicContentGadget', 'gadget_table', 'gadget_basic_content_table',
    'Container', 'container_table'
]

container_table = Table('container', metadata,
    Column('container_id', Integer, primary_key=True),
    Column('container_name', Unicode(200), nullable=True),
    Column('parent_content_id', Integer, ForeignKey('content.content_id'))
)

gadget_table = Table('gadget', metadata,
    Column('gadget_id', None, ForeignKey('revision.revision_id'), primary_key=True),
    Column('container_id', None, ForeignKey('container.container_id'), nullable=False),
    Column('gadget_order', Integer), # supports ordered list of gadgets!
)

gadget_basic_content_table = Table('gadget_basic_content', metadata,
    Column('basic_content_id', Integer, ForeignKey('gadget.gadget_id'), primary_key=True),
    Column('text', UnicodeText(), default=u"")   
)

class Container(Base):
    pass

class Gadget(Revision):
    """Gadgets can be placed in a Container on any Page or other compatible content type"""
    def render(self):
        class_name = self.__class__.__name__
        raise NotImplemented("'%s' does not have rendering capabilities" % class_name)

class BasicContentGadget(Gadget):
    """A Gadget that provides basic text rendering"""
    def render(self):
        return self.text # TODO: decorate this so the template engine doesn't escape the html

mapper(Gadget, gadget_table, inherits=Revision, polymorphic_identity=u"gadget", 
    inherit_condition=gadget_table.c.gadget_id==Revision.revision_id
)

mapper(BasicContentGadget, gadget_basic_content_table, inherits=Gadget, 
    polymorphic_identity=u"gadget_basic_content"
)

mapper(Container, container_table, properties={
    'gadgets': relation(Gadget, cascade="all, delete, delete-orphan",
        primaryjoin=and_(
            container_table.c.container_id==Gadget.container_id,
            Gadget.gadget_id==select( # By default get the LATEST version of each gadget
                [revision_table.c.revision_id],
                revision_table.c.content_id==Gadget.content_id,
                order_by=desc(revision_table.c.revision_id),
                limit=1
            ).label('latest_revision')
        )
    )
})